import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from pylab import mpl   # 实现中文字符可视化

# 设置中文显示字体为SimHei
mpl.rcParams["font.sans-serif"] = ["SimHei"]
# 设置正常显示符号，解决负号显示为方块的问题
mpl.rcParams["axes.unicode_minus"] = False

# 画图的主题设计，使用Seaborn的主题和上下文设置
sns.set_theme()
sns.set_context('notebook')

# 加载用户行为数据集和商品数据集
data_user = pd.read_csv('user_action.csv')
df = pd.read_csv('tianchi_mobile_recommend_train_item.csv')

# 查看数据集的基本信息
print(f"整体数据的大小为: {len(data_user)}")  # 打印数据集的行数
print(f"数据集中用户数量是：{len(set(data_user['user_id']))}")  # 打印用户的唯一数量
print(f"数据集中商品数量是：{len(set(data_user['item_id']))}")  # 打印商品的唯一数量
print(f"数据集中商品类别数量是：{len(set(data_user['item_category']))}")  # 打印商品类别的唯一数量
print('\n')
# 查看数据缺失情况
missing_values = data_user.isnull().sum()
print(f"数据缺失情况:\n{missing_values}")  # 打印每列数据的缺失情况
print('\n')
# 数据预处理：将时间列拆分为日期（date）和小时（hour）
data_user['date'] = pd.to_datetime(data_user['time'].str.split(' ').str[0])  # 提取日期并转换为datetime类型
data_user['hour'] = data_user['time'].str.split(' ').str[1].astype('int64')  # 提取小时并转换为整数类型

# 转换字段类型，确保它们的格式正确
data_user = data_user.astype({
    'user_id': 'object',  # 用户ID为字符串类型
    'item_id': 'object',  # 商品ID为字符串类型
    'item_category': 'object',  # 商品类别为字符串类型
    'hour': 'int64'  # 小时为整数类型
})

# 计算每日的PV（页面浏览量）和UV（独立访客数）
pv_daily = data_user.groupby('date')['user_id'].count().reset_index(name='pv_daily')  # 按日期分组，计算每日的PV
uv_daily = data_user.groupby('date')['user_id'].nunique().reset_index(name='uv_daily')  # 按日期分组，计算每日的UV

# 可视化每日的PV和UV
fig, axes = plt.subplots(2, 1, sharex=True, figsize=(10, 8))  # 创建一个两行一列的子图
pv_daily.plot(x='date', y='pv_daily', ax=axes[0], colormap='cividis')  # 在第一个子图上绘制PV
uv_daily.plot(x='date', y='uv_daily', ax=axes[1], colormap='RdGy')  # 在第二个子图上绘制UV
axes[0].set_title('Daily Page Views (PV)')  # 设置第一个子图的标题
axes[1].set_title('Daily Unique Views (UV)')  # 设置第二个子图的标题
axes[1].set_xlabel('Date')  # 设置第二个子图的X轴标签
plt.tight_layout()  # 自动调整子图间距
plt.show()  # 显示图表

# 计算每小时的PV和UV
pv_hour = data_user.groupby('hour')['user_id'].count().reset_index(name='pv_hour')  # 按小时分组，计算每小时的PV
uv_hour = data_user.groupby('hour')['user_id'].nunique().reset_index(name='uv_hour')  # 按小时分组，计算每小时的UV

# 可视化每小时的PV和UV
fig, axes = plt.subplots(2, 1, sharex=True, figsize=(10, 8))  # 创建一个两行一列的子图
pv_hour.plot(x='hour', y='pv_hour', ax=axes[0], colormap='cividis')  # 在第一个子图上绘制PV
uv_hour.plot(x='hour', y='uv_hour', ax=axes[1], colormap='RdGy')  # 在第二个子图上绘制UV
axes[0].set_title('Hourly Page Views (PV)')  # 设置第一个子图的标题
axes[1].set_title('Hourly Unique Views (UV)')  # 设置第二个子图的标题
axes[1].set_xlabel('Hour')  # 设置第二个子图的X轴标签
plt.tight_layout()  # 自动调整子图间距
plt.show()  # 显示图表

# 分析特定日期的数据（如2014-12-12）
data_user_1212 = data_user.loc[data_user['date'] == '2014-12-12']  # 筛选出2014-12-12当天的数据
pv_hour_1212 = data_user_1212.groupby('hour')['user_id'].count().reset_index(name='1212_pv_hour')  # 计算当天每小时的PV
uv_hour_1212 = data_user_1212.groupby('hour')['user_id'].nunique().reset_index(name='1212_uv_hour')  # 计算当天每小时的UV

# 可视化2014-12-12当天的PV和UV与整体数据对比
fig, axes = plt.subplots(2, 1, sharex=True, figsize=(10, 8))  # 创建一个两行一列的子图
pv_hour.plot(x='hour', y='pv_hour', ax=axes[0], colormap='cividis')  # 绘制整体的每小时PV
pv_hour_1212.plot(x='hour', y='1212_pv_hour', ax=axes[1], colormap='RdGy')  # 绘制2014-12-12的每小时PV
axes[0].set_title('Hourly Page Views (PV) - Overall')  # 设置第一个子图的标题
axes[1].set_title('Hourly Page Views (PV) - 2014-12-12')  # 设置第二个子图的标题
axes[1].set_xlabel('Hour')  # 设置第二个子图的X轴标签
plt.tight_layout()  # 自动调整子图间距
plt.show()  # 显示图表

fig, axes = plt.subplots(2, 1, sharex=True, figsize=(10, 8))  # 创建一个两行一列的子图
uv_hour.plot(x='hour', y='uv_hour', ax=axes[0], colormap='cividis')  # 绘制整体的每小时UV
uv_hour_1212.plot(x='hour', y='1212_uv_hour', ax=axes[1], colormap='RdGy')  # 绘制2014-12-12的每小时UV
axes[0].set_title('Hourly Unique Views (UV) - Overall')  # 设置第一个子图的标题
axes[1].set_title('Hourly Unique Views (UV) - 2014-12-12')  # 设置第二个子图的标题
axes[1].set_xlabel('Hour')  # 设置第二个子图的X轴标签
plt.tight_layout()  # 自动调整子图间距
plt.show()  # 显示图表

# 基于行为类型和小时分组分析
pv_behavior = data_user.groupby(['behavior_type', 'hour'])['user_id'].count().reset_index(name='pv_behavior')  # 按行为类型和小时分组，计算每种行为的PV

# 可视化不同行为类型的PV
plt.figure(figsize=(12, 6))
sns.lineplot(x='hour', y='pv_behavior', hue='behavior_type', data=pv_behavior)  # 使用Seaborn绘制折线图，不同行为类型使用不同颜色
plt.title('Hourly Page Views (PV) by Behavior Type')  # 设置图表标题
plt.xlabel('Hour')  # 设置X轴标签
plt.ylabel('Page Views')  # 设置Y轴标签
plt.show()  # 显示图表

# 排除特定行为类型（例如点击行为）
plt.figure(figsize=(12, 6))
sns.lineplot(x='hour', y='pv_behavior', hue='behavior_type', data=pv_behavior[pv_behavior['behavior_type'] != 1])  # 排除点击行为，绘制折线图
plt.title('Hourly Page Views (PV) by Behavior Type (Excluding Clicks)')  # 设置图表标题
plt.xlabel('Hour')  # 设置X轴标签
plt.ylabel('Page Views')  # 设置Y轴标签
plt.show()  # 显示图表
